package models

import (
	"context"
	"gorm.io/gorm"

	"github.com/super-team/start-kit/tools/util"
)

type AdminModel struct {
	Model
	Name     *string `json:"name" gorm:"column:name" binding:"required"`
	Account  *string `json:"account" gorm:"column:account" binding:"required"`
	Password *string `json:"password" gorm:"column:password"`
	Phone    *string `json:"phone" gorm:"column:phone" binding:"required"`
	RoleID   *int    `json:"role_id" gorm:"column:role_id" binding:"required"`
	Status   *int    `json:"status" gorm:"column:status" binding:"required"`
}

type Admin struct {
	AdminModel
	RoleKey  *string `json:"role_key" gorm:"column:role_key"`
	RoleName *string `json:"role_name" gorm:"column:role_name"`
}

func (AdminModel) TableName() string {
	return "admin"
}

func (a *AdminModel) BeforeCreate(tx *gorm.DB) error {
	p, err := util.PasswordHash(*a.Password)
	if err != nil {
		return err
	}
	a.Password = &p
	return nil
}

func (u *AdminModel) BeforeUpdate(tx *gorm.DB) error {
	if u.Password != nil {
		p, err := util.PasswordHash(*u.Password)
		if err != nil {
			return err
		}
		u.Password = &p
	}
	return nil
}

//获取管理员信息
func GetAdminByAccount(ctx context.Context, account string) (*Admin, error) {
	admin := new(Admin)
	res := db(ctx).
		Table(admin.TableName()).
		Joins("left join `role` on `role`.id = `admin`.role_id").
		Where("admin.account = ?", account).
		Select("`admin`.*,`role`.`role_name`,`role`.`role_key`").
		First(admin)
	return admin, checkErr(res.Error)
}

func DeleteAdminByID(ctx context.Context, id int64) error {
	return db(ctx).Table("admin").WithContext(ctx).Where("id = ?", id).Delete(&Admin{}).Error
}

func (a *AdminModel) AddAdmin(ctx context.Context) error {
	return db(ctx).Create(a).Error
}

func (a *AdminModel) UpdateAdmin(ctx context.Context) error {
	updateData := map[string]interface{}{
		"name":    a.Name,
		"role_id": a.RoleID,
		"phone":   a.Phone,
		"status":  a.Status,
	}
	if a.Password != nil {
		updateData["password"] = a.Password
	}
	return db(ctx).Model(a).Where("id = ?", a.ID).Updates(updateData).Error
}

func (a *AdminModel) UpdateAdminStatus(ctx context.Context) error {
	return db(ctx).Model(a).Where("id = ?", a.ID).Update("status", a.Status).Error
}

func (a *AdminModel) UpdateAdminPwd(ctx context.Context) error {
	return db(ctx).Model(a).Where("id = ?", a.ID).Update("password", a.Password).Error
}

func GetUserList(ctx context.Context, pageIndex, pageSize int,
	search *string, status *int) (map[string]interface{}, error) {
	data := map[string]interface{}{
		"count":     0,
		"list":      []Admin{},
		"pageIndex": pageIndex,
		"pageSize":  pageSize,
	}
	total := new(int64)
	d := db(ctx).Table("admin").Joins("left join `role` on `role`.id = `admin`.role_id")
	if search != nil {
		d = d.Where("admin.name like %?% or admin.phone line %?% or admin.account like %?%",
			*search, *search, *search)
	}
	if status != nil {
		d = d.Where("admin.status = ?", *status)
	}
	if err := d.Count(total).Error; err != nil {
		return data, err
	}
	if *total <= 0 {
		return data, nil
	}
	data["count"] = total
	users := []*Admin{}
	res := d.Select("`admin`.*,`role`.`role_name`,`role`.`role_key`").
		Order("admin.created_at desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&users)
	if res.Error != nil {
		return nil, res.Error
	}
	data["list"] = users
	return data, nil
}

func GetAdminByID(ctx context.Context, id int64) (*AdminModel, error) {
	admin := new(AdminModel)
	res := db(ctx).Table("admin").Where("id = ?", id).First(admin)
	return admin, res.Error
}

func UpdateAdminRole(ctx context.Context, id, roleID int64) error {
	return db(ctx).Table("admin").Where("id = ?", id).Update("role_id", roleID).Error
}
